﻿// database servers monitoring of database sql log errors. 
// true or false test (IsEnterpriseOnline).

using System.Diagnostics;
using Wolfpack.Core.Interfaces;

namespace Wolfpack.Contrib.Checks.SqlNumericResults
{
    using System;
    using Core;
    using Core.Database.SqlServer;
    using Core.Interfaces.Entities;

    public class SqlNumericResultCheckConfig : PluginConfigBase
    {
        public string ConnectionString { get; set; }

        public string Query { get; set; }
    }

    public class SqlNumericResultCheck : IHealthCheckPlugin
    {
        public readonly SqlNumericResultCheckConfig myCheckConfig;

        public PluginDescriptor myIdentity;

        public SqlNumericResultCheck(SqlNumericResultCheckConfig checkConfig)
        {
            Logger.Debug("Starting Numeric Results Sql");
            myCheckConfig = checkConfig;

            myIdentity = new PluginDescriptor
            {
                Description = "Sql Numeric Result Check",
                TypeId = new Guid("77A49069-4A8B-4679-9595-CE1241E84E5B"),
                Name = myCheckConfig.FriendlyId
            };

            if (!myCheckConfig.ConnectionString.StartsWith("Data Source="))
            {
                myCheckConfig.ConnectionString = DecryptString.Connection(myCheckConfig.ConnectionString, "<ReplaceWithPassword>");
            }
        }

        public PluginDescriptor Identity
        {
            get { return myIdentity; }
        }

        public Status Status { get; set; }

        public void Initialise()
        {
            // do nothing
        }

        protected void ValidateConfig()
        {
            if (myCheckConfig.Query.Contains(";"))
            {
                throw new FormatException("Semi-colons are not accepted in Sql from-query statements");
            }
        }

        public void Execute()
        {
            ValidateConfig();

            var stopwatch = new Stopwatch();
            stopwatch.Start();

            var query = SqlServerStatement.Create(myCheckConfig.Query).ToString();

            try
            {
                var numericResult = RunQuery(query);
                stopwatch.Stop();

                OnPublish(false, numericResult, stopwatch.Elapsed);
            }
            catch (Exception e)
            {
                // If the result is not numeric we don't want to return anything.
            }

            Logger.Debug("SQLNumericResult Done.");
        }

        protected void OnPublish(bool result, int numericResult, TimeSpan duration)
        {
            Messenger.Publish(new HealthCheckData
            {
                Identity = Identity,
                Result = result,
                Tags = numericResult.ToString(),
                Info = string.Format("{0} returned", numericResult),
                Properties = new ResultProperties
                                 {
                                     { "NumericResult", numericResult.ToString() },
                                     { "Duration(ms)", duration.TotalMilliseconds.ToString() },
                                     { "Criteria", myCheckConfig.Query }
                                 }
            });
        }

        protected int RunQuery(string query)
        {
            int result;

            using (var cmd = SqlServerAdhocCommand.UsingSmartConnection(myCheckConfig.ConnectionString)
                .WithSql(query))
            {
                result = (int)cmd.ExecuteScalar();
            }

            return result;
        }
    }
}